
goog.provide('esn.NetworkSurveySection');

goog.require('esn.FriendChip');
goog.require('esn.FriendChipDragDropItem');
goog.require('esn.soy.networkSurveySection');
goog.require('goog.array');
goog.require('goog.dom.classes');
goog.require('goog.fx.AbstractDragDrop');
goog.require('goog.fx.DragDrop');
goog.require('goog.fx.DragDropGroup');
goog.require('goog.structs.Map');


/**
 * @param {esn.model.QuestionModel} question Model of the question to
 *     display.
 * @param {Array.<esn.model.StudentModel>} friends The user's network of
 *     friends.
 * @constructor
 */
esn.NetworkSurveySection = function(appContext, question, friends,
    opt_domHelper) {
  goog.base(this, opt_domHelper);

  if (question.getPossibleAnswers().length != 4) {
    throw new Error('A network drag drop question can only have 4 possible ' +
        'answers.');
  }

  this.appContext_ = appContext;

  this.surveyClient_ = this.appContext_.getService(
      esn.constants.ServiceId.SURVEY_CLIENT);

  this.question_ = question;

  this.friendSurveys_ = friends;

  this.movedFriends_ = new goog.structs.Map();
};
goog.inherits(esn.NetworkSurveySection, goog.ui.Component);

esn.NetworkSurveySection.EventType = {
  CONTINUE: goog.events.getUniqueId('continue')
};

esn.NetworkSurveySection.prototype.friendsContainerEl_;

esn.NetworkSurveySection.prototype.answerOneContainerEl_;

esn.NetworkSurveySection.prototype.answerTwoContainerEl_;

esn.NetworkSurveySection.prototype.answerThreeContainerEl_;

esn.NetworkSurveySection.prototype.answerFourContainerEl_;

esn.NetworkSurveySection.prototype.dragDropTargets_;

esn.NetworkSurveySection.prototype.createDom = function() {
  goog.base(this, 'createDom');

  var tmplData = {
    PossibleAnswers: this.question_.getPossibleAnswers()
  };
  this.setElementInternal(
      soy.renderAsElement(esn.soy.networkSurveySection.content, tmplData));

  this.friendsContainerEl_ = this.getElementByClass('friendsContainer');
  this.answerOneContainerEl_ =
      this.getElementByClass('answerOneContainer');
  this.answerTwoContainerEl_ =
      this.getElementByClass('answerTwoContainer');
  this.answerThreeContainerEl_ =
      this.getElementByClass('answerThreeContainer');
  this.answerFourContainerEl_ =
      this.getElementByClass('answerFourContainer');

  this.createDragDropTargets_();
  this.initDragDropTargets_();
};

esn.NetworkSurveySection.prototype.enterDocument = function() {
  goog.base(this, 'enterDocument');

  // Add listens on each target.
  goog.array.forEach(this.dragDropTargets_, function(dragDropTarget) {
    this.getHandler().listen(
        dragDropTarget,
        goog.fx.AbstractDragDrop.EventType.DRAGOVER,
        this.handleFriendDragOver_);

    this.getHandler().listen(
        dragDropTarget,
        goog.fx.AbstractDragDrop.EventType.DRAGOUT,
        this.handleFriendDragOut_);

    this.getHandler().listen(
        dragDropTarget,
        goog.fx.AbstractDragDrop.EventType.DROP,
        this.handleFriendDrop_);
  }, this);

  this.getHandler().listen(
      this,
      esn.FriendChip.EventType.REMOVE_CLICK,
      this.handleFriendRemove_);
};

esn.NetworkSurveySection.prototype.createDragDropTargets_ = function() {
  this.dragDropTargets_ = [];
  this.dragDropTargets_.push(
      new goog.fx.DragDrop(this.answerOneContainerEl_));
  this.dragDropTargets_.push(
      new goog.fx.DragDrop(this.answerTwoContainerEl_));
  this.dragDropTargets_.push(
      new goog.fx.DragDrop(this.answerThreeContainerEl_));
  this.dragDropTargets_.push(
      new goog.fx.DragDrop(this.answerFourContainerEl_));
};

esn.NetworkSurveySection.prototype.initDragDropTargets_ = function() {
  var friendsDragDropGroup = new goog.fx.DragDropGroup();

  goog.array.forEach(this.friendSurveys_, function(friendSurvey) {
    var friendChip = new esn.FriendChip(friendSurvey, this.surveyClient_);
    friendChip.setRemoveIconVisible(false);
    this.addChild(friendChip);
    friendChip.render(this.friendsContainerEl_);
    var friendChipItem = new esn.FriendChipDragDropItem(friendChip);
    friendsDragDropGroup.addDragDropItem(friendChipItem);
    friendsDragDropGroup.setDragClass('esnFriendChipDrag');

    // If this friend has already been assigned a value than let's move it now.
    var answerValue = this.getAnswerValueForFriendChip_(friendChip);
    if (goog.isDef(answerValue)) {
      var targetContainerEl = this.getContainerForAnswerValue_(answerValue);
      this.moveFriendChip_(friendChip, targetContainerEl); 
    }
  }, this);

  // Add targets for friends drag-drop group.
  goog.array.forEach(this.dragDropTargets_, function(dragDropTarget) {
    friendsDragDropGroup.addTarget(dragDropTarget);
  });

  // Initialize each target.
  goog.array.forEach(this.dragDropTargets_, function(dragDropTarget) {
    dragDropTarget.init();
  });
 
  friendsDragDropGroup.init();
};

esn.NetworkSurveySection.prototype.handleFriendDragOver_ = function(e) {
  var targetContainerEl = e.dropTargetItem.element;
  goog.dom.classes.add(targetContainerEl, 'dragOver');
};

esn.NetworkSurveySection.prototype.handleFriendDragOut_ = function(e) {
  var targetContainerEl = e.dropTargetItem.element;
  goog.dom.classes.remove(targetContainerEl, 'dragOver');
};

esn.NetworkSurveySection.prototype.handleFriendDrop_ = function(e) {
  var friendChip = e.dragSourceItem.getData();
  var targetContainerEl = e.dropTargetItem.element;
  this.moveFriendChip_(friendChip, targetContainerEl);
  goog.dom.classes.remove(targetContainerEl, 'dragOver');
  // Save changes to the survey for the selected friend.
  this.updateFriendSurvey_(friendChip, this.getAnswerValue_(targetContainerEl));
};

esn.NetworkSurveySection.prototype.moveFriendChip_ = function(friendChip,
    targetContainerEl) {
  // Update moved friends map.
  this.movedFriends_.set(friendChip.getId(), friendChip);
  // Move friend chip.
  goog.dom.removeNode(friendChip);
  goog.dom.appendChild(targetContainerEl, friendChip.getElement());
};

esn.NetworkSurveySection.prototype.getAnswerValue_ = function(containerEl) {
  switch (containerEl) {
    case this.answerOneContainerEl_:
      return 1;
    case this.answerTwoContainerEl_:
      return 2;
    case this.answerThreeContainerEl_:
      return 3;
    case this.answerFourContainerEl_:
      return 4;
  }
  throw new Error('Undefined answer container.');
};

esn.NetworkSurveySection.prototype.getAnswerValueForFriendChip_ = function(
    friendChip) {
  switch (this.question_.getId()) {
    case esn.NetworkSurveyQuestionId.ASK_ADVICE:
      return friendChip.getSurvey().getAskAdviceLevel();
    case esn.NetworkSurveyQuestionId.FREQUENY:
      return friendChip.getSurvey().getInteractionLevel();
    case esn.NetworkSurveyQuestionId.FRIENDSHIP:
      return friendChip.getSurvey().getFriendshipLevel();
    case esn.NetworkSurveyQuestionId.TRUST:
      return friendChip.getSurvey().getTrustLevel();
    default:
      throw new Error('Undefined network survey question ID.');
  }
};

esn.NetworkSurveySection.prototype.getContainerForAnswerValue_ = function(
    answerValue) {
  switch (answerValue) {
    case 1:
      return this.answerOneContainerEl_;
    case 2:
      return this.answerTwoContainerEl_;
    case 3:
      return this.answerThreeContainerEl_;
    case 4:
      return this.answerFourContainerEl_;
  }
  throw new Error('Undefined answer value.');
};

esn.NetworkSurveySection.prototype.updateFriendSurvey_ = function(friendChip,
    answerValue) {
  // Update the survey associated with the given friend.
  var surveyDoa = friendChip.getSurveyDoa();
  var surveyModel = surveyDoa.getModel();
  switch (this.question_.getId()) {
    case esn.NetworkSurveyQuestionId.ASK_ADVICE:
      surveyModel.setAskAdviceLevel(answerValue);
      break;
    case esn.NetworkSurveyQuestionId.FREQUENY:
      surveyModel.setInteractionLevel(answerValue);
      break;
    case esn.NetworkSurveyQuestionId.FRIENDSHIP:
      surveyModel.setFriendshipLevel(answerValue);
      break;
    case esn.NetworkSurveyQuestionId.TRUST:
      surveyModel.setTrustLevel(answerValue);
      break;
    default:
      throw new Error('Undefined network survey question ID.');
  }
  surveyDoa.save();
};

esn.NetworkSurveySection.prototype.areAllFriendsMoved_ = function() {
  return this.friendSurveys_.length == this.movedFriends_.getCount();
};
